{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fc72d98f-8993-4bd4-a545-23d122f3df71",
   "metadata": {},
   "source": [
    "# H₂ Molecule Homework Assignment\n",
    "### Quantum Software Development Journey: From Theory to Application with Classiq - Part 3\n",
    "\n",
    "- Similarly to what we have done in class, in this exercise we will implement the VQE on H2 molecule.\n",
    "- This time instead of using the built-in methods and functions (such as `Molecule` and `MoleculeProblem`) to difne and solve the problem, you will be provided with a two qubits Hamiltonian."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56eda6d8-76c4-4862-b914-0c4598d67274",
   "metadata": {},
   "source": [
    "## Submission\n",
    "- Submit the completed Jupyter notebook and report via GitHub. Ensure all files are correctly named and organized.\n",
    "- Use the Typeform link provided in the submission folder to confirm your submission.\n",
    "\n",
    "## Additional Resources\n",
    "- [Classiq Documentation](https://docs.classiq.io/latest/)\n",
    "- The notebook from live session #3\n",
    "\n",
    "## Important Dates\n",
    "- **Assignment Release:** 22.5.2024\n",
    "- **Submission Deadline:** 3.6.2024 (7 A.M GMT+3)\n",
    "\n",
    "---\n",
    "\n",
    "Happy coding and good luck!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d41e969d-f6a7-4ff7-9660-19ce6c97ba6b",
   "metadata": {},
   "source": [
    "### Part 1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f710d6f4-d40b-42d5-b524-c6acb8059fe2",
   "metadata": {},
   "source": [
    "Given the following Hamiltonian:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ba8a6f1-3259-4492-a1ca-3abde7530cd4",
   "metadata": {},
   "source": [
    "$$\n",
    "\\hat{H} = -1.0523 \\cdot (I \\otimes I) + 0.3979 \\cdot (I \\otimes Z) - 0.3979 \\cdot (Z \\otimes I) - 0.0112 \\cdot (Z \\otimes Z) + 0.1809 \\cdot (X \\otimes X)\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "736d275c-9a5a-4c08-b891-3078430dc6c1",
   "metadata": {},
   "source": [
    "Complete the following code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "19266c11-6acc-4edb-910f-2d0dfe80a6c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "from classiq import *\n",
    "\n",
    "HAMILTONIAN = QConstant(\"HAMILTONIAN\", List[PauliTerm], [...]) #TODO: Complete Hamiltonian"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "0bb68899-2076-45c0-8868-131f38aa3b78",
   "metadata": {},
   "outputs": [],
   "source": [
    "@qfunc\n",
    "def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:\n",
    "    # TODO: Create an ansatz which allows each qubit to have arbitrary rotation\n",
    "\n",
    "\n",
    "@cfunc\n",
    "def cmain() -> None:\n",
    "    res = vqe(\n",
    "        ..., # TODO: complete the missing argument\n",
    "        False,\n",
    "        [],\n",
    "        optimizer=Optimizer.COBYLA,\n",
    "        max_iteration=1000,\n",
    "        tolerance=0.001,\n",
    "        step_size=0,\n",
    "        skip_compute_variance=False,\n",
    "        alpha_cvar=1.0,\n",
    "    )\n",
    "    save({\"result\": res})\n",
    "\n",
    "qmod = #TODO: complete the line, use classical_execution_function\n",
    "qprog = synthesize(qmod)\n",
    "# show(qprog)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "0563c1a8-7aec-4da9-9105-6b16c5c24382",
   "metadata": {},
   "outputs": [],
   "source": [
    "execution = execute(qprog)\n",
    "res = execution.result()\n",
    "# execution.open_in_ide()\n",
    "vqe_result = #TODO: complete the line"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "de17cfc0-8e64-4493-b4c2-4a97fc9797a0",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "11\n",
      "Optimal parameters: {'angles_0': -3.0292653800801213, 'angles_1': 0.13084292242999915, 'angles_2': -5.614248543217801}\n",
      "Eigenstate: {'10': (0.07328774624724109+0j), '11': (0.07328774624724109+0j), '01': (0.9946144039274718+0j)}\n"
     ]
    }
   ],
   "source": [
    "print(f\"Optimal energy: {vqe_result.energy}\")\n",
    "print(f\"Optimal parameters: {vqe_result.optimal_parameters}\")\n",
    "print(f\"Eigenstate: {vqe_result.eigenstate}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5df11dfc-3e3a-4191-bd47-d522ca3dcbfa",
   "metadata": {},
   "source": [
    "Does it similar to the `optimal energy` we calculated in class? \\\n",
    "Does it similar to the `total energy` we calculated in class?"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f0e0bea-b12f-43ad-94e8-100fedf2b57f",
   "metadata": {},
   "source": [
    "### Part 2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66882248-de08-4a6e-b33c-647f015f7d79",
   "metadata": {},
   "source": [
    "**Now, we want to have a more interesting ansatz in our `main`.**  \n",
    "Add **one** line of code to the `main` function you created in Part 1 that creates **entanglement** between the two qubits.  \n",
    "Which gate should you use?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "bb39be9e-4994-44e5-84d8-c99bc8b77145",
   "metadata": {},
   "outputs": [],
   "source": [
    "@qfunc\n",
    "def main(q: Output[QArray[QBit]], angles: CArray[CReal, 3]) -> None:\n",
    "    # TODO: Create an ansatz which allows each qubit to have arbitrary rotation\n",
    "\n",
    "\n",
    "\n",
    "@cfunc\n",
    "def cmain() -> None:\n",
    "    res = vqe(\n",
    "        ..., # TODO: complete the missing argument\n",
    "        False,\n",
    "        [],\n",
    "        optimizer=Optimizer.COBYLA,\n",
    "        max_iteration=1000,\n",
    "        tolerance=0.001,\n",
    "        step_size=0,\n",
    "        skip_compute_variance=False,\n",
    "        alpha_cvar=1.0,\n",
    "    )\n",
    "    save({\"result\": res})\n",
    "\n",
    "qmod = #TODO: complete the line, use classical_execution_function\n",
    "qprog = synthesize(qmod)\n",
    "# show(qprog)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "112a1590-283c-4f79-8035-72936561102d",
   "metadata": {},
   "outputs": [],
   "source": [
    "execution = execute(qprog)\n",
    "res = execution.result()\n",
    "# execution.open_in_ide()\n",
    "vqe_result = #TODO: complete the line"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "06500e4c-a04b-4cfa-a84d-41f96a0c68eb",
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'vqe_result' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[2], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOptimal energy: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[43mvqe_result\u001b[49m\u001b[38;5;241m.\u001b[39menergy\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m      2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOptimal parameters: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mvqe_result\u001b[38;5;241m.\u001b[39moptimal_parameters\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m      3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEigenstate: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mvqe_result\u001b[38;5;241m.\u001b[39meigenstate\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n",
      "\u001b[0;31mNameError\u001b[0m: name 'vqe_result' is not defined"
     ]
    }
   ],
   "source": [
    "print(f\"Optimal energy: {vqe_result.energy}\")\n",
    "print(f\"Optimal parameters: {vqe_result.optimal_parameters}\")\n",
    "print(f\"Eigenstate: {vqe_result.eigenstate}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30a635d7-2f15-4c94-a94b-f4270f17aed8",
   "metadata": {},
   "source": [
    "Does it similar to the `optimal energy` we calculated in class? \\\n",
    "Does it similar to the `total energy` we calculated in class? \\\n",
    "What can we learn about the provided  form this result Hamiltonian?"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
